package com.prawn.information.service;

import java.util.*;
import java.util.concurrent.TimeUnit;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Expression;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import javax.persistence.criteria.Selection;

import com.prawn.information.util.RedisUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.stereotype.Service;

import util.IdWorker;

import com.prawn.information.dao.PostDao;
import com.prawn.information.pojo.Post;

/**
 * 服务层
 *
 * @author Administrator
 */
@Service
public class PostService {

    @Autowired
    private PostDao postDao;

    @Autowired
    private RedisUtil redisUtil;

    @Autowired
    private IdWorker idWorker;


    /**
     * 查询全部列表
     *
     * @return
     */
    public List<Post> findAll() {
        return postDao.findByState(1);
    }

    /**
     * 查询全部列表-分页
     *
     * @return
     */
    public Page<Post> findAll(int state, int page, int size) {
        PageRequest pageRequest = PageRequest.of(page - 1, size);
        return postDao.findByState(state, pageRequest);
    }

    /**
     * 根据ID查询实体
     *
     * @param id
     * @return
     */
    public Post findById(int state, String id) {
        return postDao.findByIdAndState(id, state).get();
    }

    public Post findById(String id, String ip){
        //key序列化方式;（不然会出现乱码;）,但是如果方法上有Long等非String类型的话，会报类型转换错误；
        //所以在没有自己定义key生成策略的时候，以下这个代码建议不要这么写，可以不配置或者自己实现ObjectRedisSerializer
        //或者JdkSerializationRedisSerializer序列化方式;
//        RedisSerializer<String> redisSerializer = new StringRedisSerializer();//Long类型不可以会出现异常信息;
//        redisTemplate.setKeySerializer(redisSerializer);
////        redisTemplate.setHashKeySerializer(redisSerializer);
//        redisTemplate.setValueSerializer(redisSerializer);
//        if (!redisTemplate.hasKey(ip + "-" + id))
//            redisTemplate.opsForValue().set(ip + "-" + id, "1");

        //ip访问文章id记录，设置一天过期时间,并给阅读量加1
        if (!redisUtil.hasKey(ip + ":" + id)) {
            redisUtil.set(ip + ":" + id, "1", 1, TimeUnit.DAYS);
            redisUtil.hincr("clickPost", id, 1);
        }
        return postDao.findById(id).get();
    }

    public Optional<Post> findById(String id) {
        return postDao.findById(id);
    }

    /**
     * 增加
     *
     * @param post
     */
    public void add(Post post) {
        post.setCreationTime(new Date());
        post.setId(idWorker.nextId() + "");
        postDao.save(post);
    }

    /**
     * 修改
     *
     * @param post
     */
    public void update(Post post) {
        postDao.save(post);
    }

    /**
     * 删除
     *
     * @param id
     */
    public void deleteById(String id) {
        postDao.deleteById(id);
    }

    public Page<Post> findByUserId(String userId, List<Integer> status, int page, int size) {
        PageRequest pageRequest = PageRequest.of(page - 1, size);
        return postDao.findByUserIdAndStateIn(userId, status, pageRequest);
    }

    public Page<Post> findByExpertsId(String expertsId, int page, int size) {
        PageRequest pageRequest = PageRequest.of(page - 1, size);
        return postDao.findByExpertsIdAndState(expertsId, 1, pageRequest);
    }

    public Page<Post> findByType(String typeId, int page, int size) {
        return postDao.findByTypeIdAndState(typeId, 1, PageRequest.of(page-1,size));
    }

    public Page<Post> findByTime(int page, int size) {
        return postDao.findByStateOrderByCreationTimeDesc(1, PageRequest.of(page - 1, size));
    }

    public Page<Post> findByClickNum(int page, int size) {
        return postDao.findByStateOrderByClickNumDesc(1, PageRequest.of(page - 1, size));
    }

    public Page<Post> findByTypeAndTime(String typeId, int page, int size) {
        return postDao.findByTypeIdAndStateOrderByCreationTimeDesc(typeId, 1, PageRequest.of(page - 1, size));
    }

    public Page<Post> findByTypeAndClick(String typeId, int page, int size) {
        return postDao.findByTypeIdAndStateOrderByClickNumDesc(typeId, 1, PageRequest.of(page - 1, size));
    }
}
